package tsing.javase.ftp;


import io.netty.util.CharsetUtil;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

/**
 * @Date 2023/8/29 14:47
 *
 * FTP工具类
 */
public class FTPUtils {
    private FTPClient ftpClient;

    public static FTPUtils newInstance(String host, int port, String username, String password) throws IOException {
        FTPUtils ftpUtil = new FTPUtils();
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(host, port);
        ftpClient.login(username, password);
        ftpClient.enterLocalPassiveMode();
//        ftpClient.enterLocalActiveMode();  //切换至主动模式  本地测试时开启
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setControlEncoding(CharsetUtil.UTF_8.name());
        ftpUtil.ftpClient = ftpClient;
        return ftpUtil;
    }

    public void destroyClient() throws IOException {
        if (ftpClient != null) {
            ftpClient.disconnect();
        }
    }

    /**
     * 列出目录下的所有文件
     * @param remoteDirectory
     * @return
     * @throws IOException
     */
    public List<String> listFiles(String remoteDirectory) throws IOException {
        List<String> fileList = new ArrayList<>();
        String initialWorkingDirectory = ftpClient.printWorkingDirectory();
        ftpClient.changeWorkingDirectory(remoteDirectory);
        for (FTPFile file : ftpClient.listFiles()) {
            if (file.isFile()) {
                fileList.add(file.getName());
            }
        }
        // 切换回初始目录
        ftpClient.changeWorkingDirectory(initialWorkingDirectory);
        return fileList;
    }

    /**
     * 下载文件
     * @param remoteFileFullPath
     * @param localFileFullPath
     * @throws IOException
     */
    public void downloadFile(String remoteFileFullPath, String localFileFullPath) throws IOException {
        File localFile = new File(localFileFullPath);
        File parentDir = localFile.getParentFile();
        if (!parentDir.exists()) {
            if (parentDir.mkdirs()) {
                System.out.println("Created directory: " + parentDir.getAbsolutePath());
            } else {
                throw new IOException("Failed to create directory: " + parentDir.getAbsolutePath());
            }
        }
        try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(localFile.toPath()))) {
            boolean success = ftpClient.retrieveFile(remoteFileFullPath, outputStream);
            int replyCode = ftpClient.getReplyCode();
            if (200 == replyCode) {
                //消费一个连接,避免第二次获取文件为null的问题
                ftpClient.getReply();
            }
            if (success) {
                System.out.println("File downloaded successfully: " + remoteFileFullPath);
            } else {
                String replyString = ftpClient.getReplyString();
                throw new IOException("Failed to download file: " + remoteFileFullPath + " ,replyCode: " + replyCode + " ,replyString: " + replyString);
            }
        }



    }

    /**
     * 上传文件
     *
     * @param localFileFullPath
     * @param remoteFileFullPath
     * @throws IOException
     */
    public void uploadFile(String localFileFullPath, String remoteFileFullPath) throws IOException {
        File localFile = new File(localFileFullPath);
        if (remoteFileFullPath.lastIndexOf('/') != -1) {
            String remoteDirectory = remoteFileFullPath.substring(0, remoteFileFullPath.lastIndexOf('/'));
            // 判断目录是否存在，如果不存在则创建目录
            createRemoteDirectory(remoteDirectory);
        }
        try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(localFile.toPath()))) {
            boolean success = ftpClient.storeFile(remoteFileFullPath, inputStream);
            if (success) {
                System.out.println("File uploaded successfully: " + remoteFileFullPath);
            } else {
                throw new IOException("Failed to upload file: " + remoteFileFullPath);
            }
        }

    }

    /**
     * 删除
     *
     * @param remoteFileFullPath
     * @throws IOException
     */
    public void deleteFile(String remoteFileFullPath) throws IOException {

        boolean success = ftpClient.deleteFile(remoteFileFullPath);
        if (success) {
            System.out.println("File deleted successfully: " + remoteFileFullPath);
        } else {
            throw new IOException("Failed to delete file: " + remoteFileFullPath);
        }

    }

    public void createRemoteDirectory(String remoteDirectory) throws IOException {
        // 获取初始目录
        String initialWorkingDirectory = ftpClient.printWorkingDirectory();
        // 切换目录判断目录是否存在
        if (!ftpClient.changeWorkingDirectory(remoteDirectory)) {
            if (ftpClient.makeDirectory(remoteDirectory)) {
                System.out.println("Created directory: " + remoteDirectory);
            } else {
                throw new IOException("Failed to create directory: " + remoteDirectory);
            }
        }
        // 切换回初始目录
        ftpClient.changeWorkingDirectory(initialWorkingDirectory);
    }


    // 复制FTP服务器的文件到指定路径
    public boolean copyFile(String fromPath, String toPath) throws IOException {
        OutputStream outputStream = new FileOutputStream(toPath);
        boolean success = ftpClient.retrieveFile(fromPath, outputStream);
        outputStream.close();
        if (!success) {
            throw new IOException("Unable to copy file from " + fromPath + " to " + toPath);
        }
        return success;
    }

    public static void main(String[] args) throws IOException {
        String host = "192.168.137.200";
        int port = 21;
        String username = "root";
        String password = "root";
        FTPUtils ftpUtil = FTPUtils.newInstance(host, port, username, password);
        FTPClient ftpClient = ftpUtil.ftpClient;
        String remotePath = "/data/ftp/ftpuser/upload";
        String remoteBakPath = "/data/ftp/ftpuser/upload_bak";
        String localFilePath = "/data/ftp/ftpuser/download";
        String localFileBakPath = "/data/ftp/ftpuser/download_bak";

        // 复制
        try {
            List<String> list = ftpUtil.listFiles(localFilePath);
            System.out.println("list:" + list);
            if (!CollectionUtils.isEmpty(list)) {
                String local = "";
                String remote = "";
                String remoteBak = "";
                for (String s : list) {
                    local = localFilePath + "/" + s;
                    remote = remotePath + "/" + s;
                    remoteBak = remoteBakPath + "/" + s;
                    System.out.printf("local :%s", local + "\n");
                    System.out.printf("remote :%s", remote + "\n");
                    System.out.printf("remoteBak :%s", remoteBak + "\n");

                    ftpUtil.downloadFile(local, remote);
        /*            boolean flag = ftpUtil.copyFile(local, remote);
                    System.out.println(flag);
                    if (flag) {
                        System.out.println("File downloaded successfully: " + remote);
                    } else {
                        String replyString = ftpClient.getReplyString();
                    }*/
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 上传
/*        System.out.println(remotePath);
        List<String> list = ftpUtil.listFiles(remotePath);
        System.out.println(list);
        remotePath = remotePath + "/" + "20230828_cancel.txt";
        localFilePath = localFilePath + "/" + "20230828_order1.txt";
        // 上传文件
        // 切换回初始目录
        String initialWorkingDirectory = ftpClient.printWorkingDirectory();
        ftpClient.changeWorkingDirectory(initialWorkingDirectory);
        ftpUtil.uploadFile("G:\\kc_data\\Test\\20230828_order1.txt", localFilePath);*/


        //  下载
/*        try {
            // 如果FTP用户没有配置切换目录权限，则在默认目录
            // 给FTP设置切换目录权限
            ftpUtil.downloadFile("/data/ftp/ftpuser/download/20230828_order1.txt","G:\\kc_data\\Test\\20230828_order1.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }*/


    }




}
